//============================================================================
// Name        : observer_pattern.cpp
// Author      : Tony
// Version     :
// Copyright   : GPLv2
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <vector>
using namespace std;
class Subject;
class Temperature;
class Observer
{
public:
	virtual ~Observer(){}
	virtual void update(Subject* subject) = 0;
};

class Subject
{
	typedef vector<Observer*> Observers;
	Observers observers;
public:
	virtual ~Subject(){};
	void addObserver(Observer* observer)
	{
		observers.push_back(observer);
	}
	void removeObserver(Observer* observer)
	{
		for (typename Observers::iterator it = observers.begin();
				it != observers.end(); ++it)
		{
			if (*it == observer)
			{
				observers.erase(it);
				break;
			}
		}
		//typename Observers::iterator it = std::find(observers.begin(), observers.end(), observer);
		//observers.erase(it);
	}
	virtual double getValue() = 0;
protected:
	virtual void notify()
	{
		for (typename Observers::iterator it = observers.begin();
				it != observers.end(); ++it)
		{
			(*it)->update(this);
		}
	}
};

class Temperature : public Subject
{
public:
	Temperature(double value) : value(value) {}
	double getValue()
	{
		return this->value;
	}
	void setValue(double value)
	{
		this->value = value;
		notify();
	}

private:
	double value;
};

class Supervisor : public Observer
{
public:
	Supervisor(Subject* subject) : subject(subject)
	{
		subject->addObserver(this);
	}
	~Supervisor()
	{
		subject->removeObserver(this);
	}
	void update(Subject* subject)
	{
		cout<<"data updated! new data: "<<subject->getValue()<<endl;
	}

private:
	Subject* subject;

};

int main() {
	Temperature t(37.2);
	Supervisor supervisor(&t);
	t.setValue(39.1);
	t.setValue(18.9);
	t.setValue(23.6);
	return 0;
}
